﻿using Assets.Scripts.AI;
using JetBrains.Annotations;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using UnityEngine;
using UnityEngine.UI;
using static UnityEditor.PlayerSettings;
using Assets.Scripts.Map;

namespace Assets.Scripts.Map
{
    public class MapGameObject : MonoBehaviour
    {

        public int mapHeight = 10;
        public int mapWidth = 10;

        public int unitSpace_x = 12;
        public int unitSpace_y = 12;
        [Range(0, 1)]
        public float blockRate = 0.2f;

        public MapData data;

        /// <summary>
        /// 地图单元prefab
        /// </summary>
        public MapUnit_2D prefabUnit;
        public List<MapUnit_2D> unitList = new();

        private MapUnit_2D start;
        private MapUnit_2D end;

        public Sprite startIcon;
        public Sprite endIcon;

        public Button btnAstar;

        public void GenerateMap()
        {
            data.Regenerate(mapHeight, mapWidth, blockRate);
        }

        public void DrawMap()
        {
            Image img = transform.GetComponent<Image>();
            img.GetComponent<RectTransform>().sizeDelta = new Vector2(mapWidth * unitSpace_x, mapHeight * unitSpace_y);

            for (int y = 0; y < mapHeight; y++)
            {
                for (int x = 0; x < mapWidth; x++)
                {
                    int idx = y * mapWidth + x;
                    if (idx >= unitList.Count)
                    {
                        MapUnit_2D newUnit = Instantiate<MapUnit_2D>(prefabUnit);
                        newUnit.transform.SetParent(transform, false);
                        unitList.Add(newUnit);
                    }

                    MapUnit_2D unit = unitList[idx];
                    unit.Init(x, y);
                    unit.SetOnClick((unit, xx, yy) =>
                    {
                        if (unit.State == UnitState.Obstacle)
                        {
                            return;
                        }

                        if (start == null)
                        {
                            start = unit;
                            unit.SetIocn(startIcon);
                        }
                        else if (end == null)
                        {
                            end = unit;
                            unit.SetIocn(endIcon);
                        }
                        else
                        {
                            start.SetIocn(null);
                            end.SetIocn(null);
                            start = unit;
                            end = null;
                            unit.SetIocn(startIcon);
                        }
                    });
                    unit.transform.localPosition = new Vector3(x * unitSpace_x + unitSpace_x / 2, y * unitSpace_y + unitSpace_y / 2, 0);
                    DrawUnit(x, y);
                }
            }
        }

        public void DrawUnit(int x, int y)
        {
            MapUnit_2D unit = unitList[y * mapWidth + x];
            bool canPass = data.Get(x, y);
            if (canPass)
            {
                unit.SetState(UnitState.None);
            }
            else
            {
                unit.SetState(UnitState.Obstacle);
            }
        }

        public void DrawUnit(AStarUnit unit, UnitState state)
        {
            int x = unit.Pos.X;
            int y = unit.Pos.Y;
            MapUnit_2D cell = unitList[y * mapWidth + x];
            cell.SetState(state);
            cell.SetValue(unit.F, unit.G, unit.H);
        }

        private void Start()
        {
            int[,] a = new int[3, 4] {
                {0, 1, 2, 3} ,   /*  初始化索引号为 0 的行 */
                {4, 5, 6, 7} ,   /*  初始化索引号为 1 的行 */
                {8, 9, 10, 11}   /*  初始化索引号为 2 的行 */
            };

            Debug.Log(a[1, 2]);
            Debug.Log(a.Length);
            Debug.Log(a.GetLength(0));
            Debug.Log(a.GetLength(1));
            //Debug.Log(a.);

            if (!data.Inited)
            {
                data.Init();
            }
            mapHeight = data.Height;
            mapWidth = data.Width;
            DrawMap();

            btnAstar.onClick.RemoveAllListeners();
            btnAstar.onClick.AddListener(() =>
            {
                CompleteAStar();
            });
        }

        private void Update()
        {
            if (Input.GetKeyDown(KeyCode.G))
            {

                GenerateMap();
                DrawMap();
            }

            if (Input.GetKeyDown(KeyCode.Space))
            {
                ItorAstar();
            }
        }

        private AStarEnum aStarEnum;

        //向前迭代 A 星寻路
        public void ItorAstar()
        {
            if (aStarEnum == null)
            {
                aStarEnum = new(data, new V2() { X = start.x, Y = start.y }, new V2 { X = end.x, Y = end.y });
            }
            else
            {
                if (aStarEnum.MoveNext())
                {
                    //AStarUnit current = aStarEnum.Current;
                    //draw unit
                    for (int i = 0; i < aStarEnum.list_open.Count; i++)
                    {
                        V2 pos = aStarEnum.list_open[i];
                        DrawUnit(aStarEnum.GetByPos(pos), UnitState.Checking);
                    }

                    for (int i = 0; i < aStarEnum.list_close.Count; i++)
                    {
                        V2 pos = aStarEnum.list_close[i];
                        DrawUnit(aStarEnum.GetByPos(pos), UnitState.Abandoned);
                    }

                    //DrawUnit(current, UnitState.Checked);
                }
                else
                {
                    for (int i = 0; i < aStarEnum.Path.Count; i++)
                    {
                        V2 pos = aStarEnum.Path[i];
                        DrawUnit(aStarEnum.GetByPos(pos), UnitState.Checked);
                    }

                    aStarEnum.Dispose();
                    aStarEnum = null;
                }
            }
        }

        public void CompleteAStar()
        {
            if (aStarEnum == null)
            {
                aStarEnum = new(data, new V2() { X = start.x, Y = start.y }, new V2 { X = end.x, Y = end.y });
                while (aStarEnum.MoveNext())
                {

                }

                for (int i = 0; i < aStarEnum.Path.Count; i++)
                {
                    V2 pos = aStarEnum.Path[i];
                    DrawUnit(aStarEnum.GetByPos(pos), UnitState.Checked);
                }
                aStarEnum.Dispose();
                aStarEnum = null;
            }
        }
    }
}